package jp.sourceforge.akjrcp.ui;

import java.io.File;
import java.util.List;

import jp.sourceforge.akjrcp.ffmpeg.FFMpegFLVParser;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegFileInfomation;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegInput;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegOptions;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegPreference;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class GenericParametersFFMpegPreference extends FFMpegPreference {
	public static Log log=LogFactory.getLog(GenericParametersFFMpegPreference.class);
public static final String EXTENSION="EXTENSION";
public static final String TWO_PASS_ENCODE="TWO_PASS_ENCODE";
public static final String MAX_FRAME_RATE="MAX_FRAME_RATE";

public static final String AFTER_ACTION="AFTER_ACTION";

public static final String USE_AVISYNTH="drop_use_avisynth";//

public static final String[] SYSTEM_KEYS={EXTENSION,TWO_PASS_ENCODE,MAX_FRAME_RATE,AFTER_ACTION,USE_AVISYNTH};
private GenericParameters genericParameters;

private String[] addOptions;
public GenericParametersFFMpegPreference(GenericParameters setting) {
	setGenericParameters(setting);
	setFormat(setting.getParameters().get(FFMpegOptions.OPTION_FORMAT));//for two pass need it isTwopassNeedAudio()
	
	setVideoCodec(setting.getParameters().get(FFMpegOptions.OPTION_VIDEO_CODEC));
	
	
	setAudioCodec(setting.getParameters().get(FFMpegOptions.OPTION_AUDIO_CODEC));
	
	setExtension(setting.getParameters().get(EXTENSION));
	
	if(setting.getParameters().get(FFMpegOptions.OPTION_DISABLE_VIDEO)!=null){
		setEnableVideo(false);
		}

	if(setting.getParameters().get(FFMpegOptions.OPTION_DISABLE_AUDIO)!=null){
		setEnableAudio(false);
		}
	
	String format=setting.getParameters().get(FFMpegOptions.OPTION_FORMAT);
	
	if(format!=null && format.length()>0){
		setFormat(format);
		
	}
}

public void addLastOptions(FFMpegInput[] input,List params){
	
	
	//get videoinfo.
	
	if(genericParameters!=null){
	//setup maxfr
	String maxValue=genericParameters.getParameters().get(MAX_FRAME_RATE);
	String rate=genericParameters.getParameters().get("r");//-r is framerate
	//log.infov:"+maxValue+",r="+rate);
	//maxrate effects only if rate not setted.
	if(maxValue!=null && rate==null){
		try{
		double maxFrameRate=Double.parseDouble(maxValue);
		FFMpegFileInfomation info=getVideoInfomation(getFfmpegPath(),input);
		
		if(info!=null ){
			if(info.getVideoRate()>0){
			log.warn("rate:"+maxFrameRate+","+info.getVideoRate());
			double r=Math.min(maxFrameRate, info.getVideoRate());
			if(r>0){
				log.info("maxrate:set rate "+r);
				genericParameters.getParameters().put("r",""+r);//set -r
			}else{
				log.warn("invalid rate:"+info.getVideoBitrate());
				}
			}else{
			log.warn("video rate is 0 and cant set maxframerate");
			log.info(info.getText());
			}
		}else{
			log.warn("info null and cant set maxframerate");
			//let be go
		}
		}catch(Exception e){
			log.warn("wrong max frame rete double:"+maxValue);
		}
	}else{
		//use -r 
	}
	
	String args[]=genericParameters.toArgParams();

	String tmpSize=null;//for add last -s option
	for (int i = 0; i < args.length; i++) {
		
		 boolean skip=false;
		 if(args[i].equals("-f")){
			//because setFormat() called in GenericParametersFFMpegPreference
			if(getFormat()!=null && getFormat().equals(args[i+1])){
			i++;//skip next
			skip=true;
			}
		}
		
		//support newer codec pattern
		if(getGeneration()==2){
		if(args[i].equals("-acodec")){
			args[i+1]=toSuiteAudioCodec(args[i+1],getGeneration());
			}
		
		if(args[i].equals("-vcodec")){
			args[i+1]=toSuiteVideoCodec(args[i+1],getGeneration());
			}
		}
		
		//ignore acodec
		if(args[i].equals("-acodec") && getAudioCodec()!=null){
			i++;//skip next
			skip=true;
			}
		
		//ignore vcodec
		if(args[i].equals("-vcodec") && getVideoCodec()!=null){
			i++;//skip next
			skip=true;
			}
		
		
		if(args[i].equals("-s")){
		//add size options last for working cropping correctlly
		tmpSize=args[i+1];
		i++;//skip next
		skip=true;
		}
		
		if(!skip){
		params.add(args[i]);
		}
	}
	
	
	//last  -s is better
	if(tmpSize!=null){
		params.add("-s");
		params.add(tmpSize);
	}
	}else{
		log.warn("genericParameters=null");
	}
	
	//additional option
	if(addOptions!=null){
		for (int i = 0; i < addOptions.length; i++) {
			params.add(addOptions[i]);
		}
	}
	
}

public static FFMpegFileInfomation getVideoInfomation(String ffmpegPath,FFMpegInput[] inputs){
	for(int i=inputs.length-1;i>=0;i--){
		FFMpegFileInfomation info=new FFMpegFLVParser(ffmpegPath).parseFile(new File(inputs[i].getPath()));
		if(info!=null){
			if(info.isHaveVideo()){
				return info;
			}
		}
	}
	return null;
}

public GenericParameters getGenericParameters() {
	return genericParameters;
}

public void setGenericParameters(GenericParameters genericParameters) {
	this.genericParameters = genericParameters;
}

public boolean isTwoPassEncode() {
	if(genericParameters!=null){
		String twopass=genericParameters.getParameters().get(TWO_PASS_ENCODE);
		if(twopass!=null){
			return true;
		}else{
			return false;
		}
	}
	log.info("twopass is not in map");
	return super.isTwoPassEncode();
}

public String getExtension(){
	if(genericParameters!=null){
		String ext=genericParameters.getParameters().get(EXTENSION);
		if(ext!=null){
			return ext;
		}
	}
	log.info("extension is not in map");
	return super.getExtension();
}

public int getGuessVideoBitrate(FFMpegFileInfomation info){
	int ret=0;
	String bValue=genericParameters.getParameters().get("b");
	if(bValue!=null){
		try{
			if(bValue.toLowerCase().endsWith("k")){
				ret=(int) Double.parseDouble(bValue.substring(0,bValue.length()-1));
			}else if(bValue.toLowerCase().endsWith("m")){
				ret=(int) Double.parseDouble(bValue.substring(0,bValue.length()-1))*1024;
			}else{
				ret= (int)Double.parseDouble(bValue)/1024;
			}
			}catch(Exception e){
				log.warn("wrong b or br:"+bValue);
			}
	}else{
		if(info!=null){
			ret=info.getVideoBitrate();
		}
	}
	return ret;
}

public int getGuessAudioBitrate(FFMpegFileInfomation info){
	int ret=0;
	String bValue=genericParameters.getParameters().get("ab");
	if(bValue!=null){
		try{
		if(bValue.toLowerCase().endsWith("k")){
			ret=(int) Double.parseDouble(bValue.substring(0,bValue.length()-1));
		}else if(bValue.toLowerCase().endsWith("m")){
			ret=(int) Double.parseDouble(bValue.substring(0,bValue.length()-1))*1024;
		}else{
			ret= (int)Double.parseDouble(bValue)/1024;
		}
		}catch(Exception e){
			log.warn("wrong b or br:"+bValue);
		}
	}else{
		if(info!=null){
			ret=info.getAudioBitrate();
		}
	}
	return ret;
}

public String[] getAddOptions() {
	return addOptions;
}

public void setAddOptions(String[] addOptions) {
	this.addOptions = addOptions;
}


}
